//package com.lch.webdemo.util;
//
//import com.google.common.collect.Lists;
//
//import org.apache.commons.lang.StringUtils;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.dao.DataAccessException;
//import org.springframework.data.redis.connection.RedisConnection;
//import org.springframework.data.redis.core.RedisCallback;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.data.redis.core.script.DefaultRedisScript;
//import org.springframework.data.redis.serializer.RedisSerializer;
//import org.springframework.stereotype.Component;
//
//import java.util.Collection;
//import java.util.List;
//import java.util.Map;
//import java.util.Set;
//import java.util.concurrent.TimeUnit;
//
//import javax.annotation.Resource;
//
//
///**
// * @author wangyuan
// * @Date 2018/09/27 09:44
// */
//@Component
//@SuppressWarnings("all")
//public class RedisUtil {
//
//    private static final Logger LOGGER = LoggerFactory.getLogger(RedisUtil.class);
//
//    @Resource
//    RedisTemplate<String, String> redisTemplate;
//
//    /**
//     * 设置key超时时间
//     *
//     * @param key     缓存的key
//     * @param timeout 时间值
//     * @param unit    时间单位
//     */
//    public void expire(String key, long timeout, TimeUnit unit) {
//        redisTemplate.expire(key, timeout, unit);
//    }
//
//    /**
//     * 缓存key-value
//     *
//     * @param key   缓存的key
//     * @param value 缓存的value
//     */
//    public void set(String key, String value) {
//        redisTemplate.opsForValue().set(key, value);
//    }
//
//    /**
//     * 缓存key-value并指定过期时间，时间单位：秒
//     *
//     * @param key        缓存的key
//     * @param value      缓存的value
//     * @param expireTime 缓存的过期时间
//     */
//    public void set(String key, String value, Long expireTime) {
//        redisTemplate.opsForValue().set(key, value, expireTime, TimeUnit.SECONDS);
//    }
//
//    /**
//     * 缓存key-value并指定过期时间
//     *
//     * @param key        缓存的key
//     * @param value      缓存的value
//     * @param expireTime 缓存的过期时间
//     * @param timeUnit   时间单位
//     */
//    public void set(String key, String value, Long expireTime, TimeUnit timeUnit) {
//        redisTemplate.opsForValue().set(key, value, expireTime, timeUnit);
//    }
//
//    /**
//     * 将 key 的值设为 value ，当且仅当 key 不存在。
//     *
//     * @param key   缓存的key
//     * @param value 缓存的value
//     * @return true设置成功，false设置失败
//     */
//    public boolean setNX(String key, String value) {
//        return redisTemplate.opsForValue().setIfAbsent(key, value);
//    }
//
//    /**
//     * 设置缓存超时时间
//     *
//     * @param key        缓存的key
//     * @param expireTime 缓存的超时时间
//     * @param timeUnit   时间单位
//     */
//    public void setEX(String key, Long expireTime, TimeUnit timeUnit) {
//        redisTemplate.expire(key, expireTime, timeUnit);
//    }
//
//    /**
//     * 获取缓存的值
//     *
//     * @param key 缓存的key
//     * @return 缓存的value
//     */
//    public String get(String key) {
//        return redisTemplate.opsForValue().get(key);
//    }
//
//    /**
//     * 删除缓存
//     *
//     * @param key 缓存的key
//     */
//    public void delete(String key) {
//        redisTemplate.delete(key);
//    }
//
//    /**
//     * 检查key是否已经存在
//     *
//     * @return true存在，false不存在
//     */
//    public boolean exist(final String key) {
//
//        return redisTemplate.execute(new RedisCallback<Boolean>() {
//            @Override
//            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
//                Jedis jedis = (Jedis) connection.getNativeConnection();
//                return jedis.exists(key);
//            }
//        });
//
//    }
//
//    /**
//     * 自增长
//     *
//     * @param key 增长值对应的KEY
//     * @return 增长后结果
//     */
//    public Long incr(String key) {
//        return incrBy(key, 1);
//    }
//
//    /**
//     * 增长指定步长
//     *
//     * @param key  对应的key
//     * @param step 步长
//     * @return 增长后的结果
//     */
//    public Long incrBy(String key, int step) {
//        if (StringUtils.isEmpty(key)) {
//            return null;
//        }
//        return redisTemplate.opsForValue().increment(key, step);
//    }
//
//    // ==========================hash操作====================================
//
//    /**
//     * hash表添加缓存
//     *
//     * @param hashKey hash表的key
//     * @param field   哈希表域中的field
//     * @param value   哈希表域中field对应的value
//     */
//    public <T> void hSet(String hashKey, String field, T value) {
//        redisTemplate.<String, T>opsForHash().put(hashKey, field, value);
//    }
//
//    /**
//     * hash表，仅当field不存在时，添加缓存
//     *
//     * @param hashKey hash表的key
//     * @param field   哈希表域中的field
//     * @param value   哈希表域中field对用的value
//     * @return true添加成功，false添加失败
//     */
//    public <T> boolean hSetNX(String hashKey, String field, T value) {
//        return redisTemplate.<String, T>opsForHash().putIfAbsent(hashKey, field, value);
//    }
//
//    /**
//     * 同时将多个field-value设置到hash表hashKey中
//     *
//     * @param hashKey hash表的key
//     * @param map     多个field-value
//     */
//    public <T> void hMSet(String hashKey, Map<String, T> map) {
//        redisTemplate.<String, T>opsForHash().putAll(hashKey, map);
//    }
//
//    /**
//     * 获取hash表中给定的key的值
//     *
//     * @param hashKey hash表的key
//     * @param keys    指定的key
//     * @return 指定key的value列表
//     */
//    public <T> List<T> hMGet(String hashKey, String... keys) {
//        return redisTemplate.<String, T>opsForHash().multiGet(hashKey, Lists.newArrayList(keys));
//    }
//
//    /**
//     * 获取hash表中给定的key的值
//     *
//     * @param hashKey hash表的key
//     * @param keys    指定的key
//     * @return 指定key的value列表
//     */
//    public <T> List<T> hMGet(String hashKey, Collection collection) {
//        return redisTemplate.<String, T>opsForHash().multiGet(hashKey, collection);
//    }
//
//    /**
//     * 获取hash表中对应field的value
//     *
//     * @param hashKey hash表的key
//     * @param field   hash表中的field
//     * @return field对应value
//     */
//    public <T> T hGet(String hashKey, String field) {
//        return redisTemplate.<String, T>opsForHash().get(hashKey, field);
//    }
//
//    /**
//     * 获取hash表中的所有数据
//     *
//     * @param hashKey hash表的key
//     * @return 返回hash表中的所有数据
//     */
//    public <T> Map<String, T> hGetAll(String hashKey) {
//        return redisTemplate.<String, T>opsForHash().entries(hashKey);
//    }
//
//    /**
//     * 获取hash表的长度
//     *
//     * @param hashKey hash表的key
//     * @return hahs表的长度，key不存在时为0
//     */
//    public long hLen(String hashKey) {
//        return redisTemplate.opsForHash().size(hashKey);
//    }
//
//    /**
//     * 获取hash表中的所有key
//     *
//     * @param hashKey 哈希表的key
//     * @return hash表的key集合
//     */
//    public Set<String> hKeys(String hashKey) {
//        return redisTemplate.<String, Object>opsForHash().keys(hashKey);
//    }
//
//    /**
//     * 获取hash表中所有的value
//     *
//     * @param hashKey hash表的key
//     * @return hash表中的value列表
//     */
//    public <T> List<T> hVals(String hashKey) {
//        return redisTemplate.<String, T>opsForHash().values(hashKey);
//    }
//
//    /**
//     * 删除hash表中指定的key
//     *
//     * @param hashKey hash表的key
//     * @param keys    指定的key
//     * @return 删除个数
//     */
//    public Long hDel(String hashKey, Object... keys) {
//        return redisTemplate.opsForHash().delete(hashKey, keys);
//    }
//
//    // ==========================list操作====================================
//
//    /**
//     * 从list头开始取出指定头尾的list集合，range是一个闭区间
//     *
//     * @param listKey key值
//     * @param start   开始下标
//     * @param end     结束下标
//     */
//    public List<String> range(String listKey, long start, long end) {
//        return redisTemplate.opsForList().range(listKey, start, end);
//    }
//
//    /**
//     * 获取集合的长度
//     *
//     * @param listKey 集合的key
//     * @return 集合的长度，key不存在是为0
//     */
//    public Long lLen(String listKey) {
//        return redisTemplate.opsForList().size(listKey);
//    }
//
//    /**
//     * 向list左边插入值
//     *
//     * @param listKey key值
//     * @param value   value值
//     */
//    public void lpush(String listKey, String value) {
//        redisTemplate.opsForList().leftPush(listKey, value);
//    }
//
//    /**
//     * 向list左边插入一组值
//     *
//     * @param listKey key值
//     * @param values  value值列表
//     */
//    public void lpushAll(String listKey, List<String> values) {
//        redisTemplate.opsForList().leftPushAll(listKey, values);
//    }
//
//    /**
//     * 从list的右边取出第一个值
//     *
//     * @param listKey key值
//     */
//    public String rpop(String listKey) {
//        return redisTemplate.opsForList().rightPop(listKey);
//    }
//
//    /**
//     * 向list右边插入值
//     *
//     * @param listKey key值
//     * @param value   value值
//     */
//    public void rpush(String listKey, String value) {
//        redisTemplate.opsForList().rightPush(listKey, value);
//    }
//
//    /**
//     * 向list右边插入一组值
//     *
//     * @param listKey key值
//     * @param values  value值列表
//     */
//    public void rpushAll(String listKey, List<String> values) {
//        redisTemplate.opsForList().rightPushAll(listKey, values);
//    }
//
//    /**
//     * 从list的左边取出第一个值
//     *
//     * @param listKey key值
//     */
//    public String lpop(String listKey) {
//        return redisTemplate.opsForList().leftPop(listKey);
//    }
//
//    /**
//     * 从list中移除一个value值
//     *
//     * @param listKey key值
//     * @param i       删除的个数 count > 0表头搜索,删除count个，count < 0表尾搜索，删除count个 count = 0 所有与value相等的值
//     * @param value   待删除的值
//     */
//    public void lrem(String listKey, long i, Object value) {
//        redisTemplate.opsForList().remove(listKey, i, value);
//    }
//
//    /**
//     * 利用管道命令实现批量删除
//     *
//     * @param listKey key值
//     * @param values  待删除的values值
//     */
//    public void lrems(final String listKey, final List<String> values) {
//        try {
//            final RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
//            redisTemplate.executePipelined(new RedisCallback<Object>() {
//                @Override
//                public Object doInRedis(RedisConnection connection) throws DataAccessException {
//                    byte[] listKeyBtye = serializer.serialize(listKey);
//                    for (String value : values) {
//                        byte[] valueByte = serializer.serialize(value);
//                        connection.lRem(listKeyBtye, 0, valueByte);
//                    }
//                    return null;
//                }
//            });
//        } catch (Exception e) {
//            LOGGER.info("使用管道操作出错:{}", e);
//        }
//    }
//    // ===========================set操作====================================
//
//    /**
//     * 插入一个或多个member元素到key中，已存在的将被忽略
//     *
//     * @param setKey set的key
//     * @param values 一个或多个member
//     */
//    public Long sadd(String setKey, String... values) {
//        return redisTemplate.opsForSet().add(setKey, values);
//    }
//
//    /**
//     * 移除集合setKey中的一个或多个元素
//     *
//     * @param setKey set的Key
//     * @param values 一个或多个key
//     */
//    public Long srem(String setKey, Object[] values) {
//        return redisTemplate.opsForSet().remove(setKey, values);
//    }
//
//    /**
//     * 获取set中的所有成员
//     *
//     * @param setKey set的key
//     * @return Set<string>所有数据
//     */
//    public Set<String> smembers(String setKey) {
//        return redisTemplate.opsForSet().members(setKey);
//    }
//
//    // ==========================分布式锁实现==================================
//
//    private static final String LOCK_SUCCESS = "OK";
//    private static final String SET_IF_NOT_EXIST = "NX";
//    private static final String SET_WITH_EXPIRE_TIME = "PX";// PX单位是毫秒，EX单位是秒
//    private static final String PRE_LOCK = "LOCK_";
//    private static final String UNLOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
//
//    /**
//     * 获取分布式锁
//     *
//     * @param key        锁的key
//     * @param requestId  锁的value，用于释放锁，防止锁被错误释放
//     * @param expireTime 锁的过期时间，单位毫秒
//     * @return true获取锁成功，false获取锁失败
//     */
//    public boolean lock(String key, final String requestId, final Integer expireTime) {
//
//        final String realKey = getKey(key);
//        String status = redisTemplate.execute(new RedisCallback<String>() {
//            @Override
//            public String doInRedis(RedisConnection connection) throws DataAccessException {
//                Jedis jedis = (Jedis) connection.getNativeConnection();
//                return jedis.set(realKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
//            }
//        });
//        return LOCK_SUCCESS.equals(status);
//    }
//
//    /**
//     * 获取分布式锁
//     *
//     * @param lockDo 锁实体
//     * @return true获取锁成功，false获取锁失败
//     */
//    public boolean lock(LockDo lockDo) {
//        return lock(lockDo.getKey(), lockDo.getValue(), lockDo.getExpireTime());
//    }
//
//    /**
//     * 释放分布式锁
//     *
//     * @param key       锁的key
//     * @param requestId 锁的value
//     */
//    public void unlock(final String key, final String requestId) {
//        String realKey = getKey(key);
//        redisTemplate.execute(new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class),
//                Lists.newArrayList(realKey), requestId);
//    }
//
//    /**
//     * 生成锁的key
//     *
//     * @param key key的关键信息
//     * @return 锁的key
//     */
//    private String getKey(String key) {
//        return PRE_LOCK + key;
//    }
//
//    /**
//     * 释放分布式锁
//     *
//     * @param lockDo 锁实体
//     */
//    public void unlock(LockDo lockDo) {
//        unlock(lockDo.getKey(), lockDo.getValue());
//    }
//
//    /**
//     * 检查锁是否存在，主要用于异步锁的探测处理
//     *
//     * @param key 锁的key
//     * @return true存在，false不存在
//     */
//    public boolean existLock(final String key) {
//        String realKey = getKey(key);
//        return redisTemplate.hasKey(realKey);
//    }
//
//    /**
//     * 删除异步锁
//     *
//     * @param key 锁的key
//     */
//    public void deleteLock(String key) {
//        String realKey = getKey(key);
//        redisTemplate.delete(realKey);
//    }
//
//    /**
//     * 分布式锁
//     */
//    public class LockDo {
//        private String key;
//        private String value;
//        private Integer expireTime;
//
//        private LockDo() {
//            this.value = UUIDUtil.getUUID();
//        }
//
//        public LockDo(String key, Integer expireTime) {
//            this();
//            this.key = key;
//            this.expireTime = expireTime;
//        }
//
//        public LockDo(String key, String value, Integer expireTime) {
//            this.key = key;
//            this.value = value;
//            this.expireTime = expireTime;
//        }
//
//        public String getKey() {
//            return key;
//        }
//
//        public String getValue() {
//            return value;
//        }
//
//        public Integer getExpireTime() {
//            return expireTime;
//        }
//    }
//}